#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "fileutils.h"
#include "travellabel.h"
#include "location_search.h"
#include "floyd_warshall.h"
#include "genetic_algorithm.h"
#include "ant_colony_optimization.h"
#include "spfa.h"
#include "dijkstra.h"
#include "queue_network.h"
#include "a_star.h"

// MainWindow 构造函数
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    // 加载样式表
    QFile file(":/resources/MacOS.qss");
    if (file.open(QFile::ReadOnly)) {
        QString styleSheet = QLatin1String(file.readAll());
        qApp->setStyleSheet(styleSheet);
        file.close();
    }

    // 初始化用户界面
    ui->setupUi(this);

    // 设置搜索框的样式
    ui->searchLineEdit->setStyleSheet("QLineEdit { color: blue; }");

    // 加载数据
    loadData();


    // 在下拉框中添加算法选项
    ui->TSPSolution->addItem("遗传算法");
    ui->TSPSolution->addItem("蚁群算法");
    ui->RouteSolution->addItem("SPFA");
    ui->RouteSolution->addItem("dijkstra");
    ui->RouteSolution->addItem("Astar");

    // 设置 TravelLabel 的位置数据
    ui->travelLabel->setPositionsMap(positionsMap);
    ui->travelLabel->setCentralPosition(centralPosition);
    ui->travelLabel->setScaleFactor(42000.0);
    ui->travelLabel->setDrawLines(true);
    ui->travelLabel->setOrderedNames(names);

    // 计算队列长度的颜色
    calculateColorByQueueLength(10.0);

    // 连接信号和槽函数
    connect(ui->travelLabel, &TravelLabel::coordinatesClicked, this, &MainWindow::onCoordinatesClicked);
    connect(ui->listWidget, &QListWidget::currentTextChanged, this, &MainWindow::displayImage);
    connect(ui->listWidget, &QListWidget::currentTextChanged, this, &MainWindow::displayText);
    connect(ui->searchLineEdit, &QLineEdit::textChanged, this, &MainWindow::filterListItems);

    // 默认选择“故宫”作为当前项目
    QList<QListWidgetItem*> items = ui->listWidget->findItems("故宫", Qt::MatchExactly);
    if (!items.isEmpty()) {
        ui->listWidget->setCurrentItem(items.first());
    } else {
        displayImage("故宫");
    }

    // 连接菜单项的动作
    connect(ui->travelPage, &QAction::triggered, this, &MainWindow::showTravelPage);
    connect(ui->introPage, &QAction::triggered, this, &MainWindow::showIntroPage);
    connect(ui->TSP, &QPushButton::clicked, this, &MainWindow::onTSPButtonClicked);
}

// MainWindow 析构函数
MainWindow::~MainWindow()
{
    delete ui;
}

// 加载数据并初始化
void MainWindow::loadData()
{
    QString filePath = ":/resources/output.json";
    dataMap = readJsonFile(filePath);

    // 将地点名称添加到列表中，并记录位置
    for (auto it = dataMap.constBegin(); it != dataMap.constEnd(); ++it) {
        if (!it.key().contains("导航点")) {
            ui->listWidget->addItem(it.key());
        }
        positionsMap[it.key()] = QPointF(it.value().at(0), it.value().at(1));
    }
    ui->listWidget->addItem("故宫");

    // 设置“太和殿”作为中央位置
    if (positionsMap.contains("太和殿")) {
        centralPosition = positionsMap["太和殿"];
    }

    // 加载其他数据
    Intro = loadJsonIntro(":/resources/palace_introduction.json");
    names = extractHeaders(":/resources/final_adjacency_matrix.csv");
    csvData = readCsvFile(":/resources/final_adjacency_matrix.csv");
    geoData = readJsonFile(":/resources/output.json");
    distanceMatrix = convertToDistanceMatrix(csvData);
    floydMatrix = floyd(distanceMatrix);
    InterestMatrix = convertToInterestMatrix(floydMatrix);
    geoVector = initializeGeoVector(names, geoData);
}

// 显示图片
void MainWindow::displayImage(const QString &itemName)
{
    QString imagePath = ":/resources/" + itemName + ".jpg";
    QPixmap pixmap(imagePath);

    if (pixmap.isNull()) {
        ui->mapLabel->setText("无法加载图片: " + itemName);
    } else {
        QSize labelSize = ui->mapLabel->size();
        QPixmap scaledPixmap = pixmap.scaled(labelSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
        ui->mapLabel->setPixmap(scaledPixmap);
        ui->mapLabel->setScaledContents(false);
    }
}

// 显示文本信息
void MainWindow::displayText(const QString &itemName)
{
    QFont font;
    font.setFamily("华文楷体");
    font.setPointSize(12);
    ui->textEdit->setFont(font);

    if (Intro.contains(itemName)) {
        ui->textEdit->setText(Intro[itemName]);
    } else {
        ui->textEdit->setText("暂无介绍");
    }
}

// 显示旅行页面
void MainWindow::showTravelPage()
{
    ui->stackedWidget->setCurrentWidget(ui->travelWidget);
}

// 显示介绍页面
void MainWindow::showIntroPage()
{
    ui->stackedWidget->setCurrentWidget(ui->introwidget);
}

// 过滤列表项
void MainWindow::filterListItems(const QString &text)
{
    // 遍历所有列表项，根据搜索文本隐藏不匹配的项
    for (int i = 0; i < ui->listWidget->count(); ++i) {
        QListWidgetItem *item = ui->listWidget->item(i);
        if (item->text().contains(text, Qt::CaseInsensitive)) {
            item->setHidden(false);
        } else {
            item->setHidden(true);
        }
    }
}

// 搜索按钮点击事件
void MainWindow::onSearchButtonClicked()
{
    QString searchText = ui->searchLineEdit->text();

    // 从列表中创建地点名称的向量
    QVector<QString> locations;
    for (int i = 0; i < ui->listWidget->count(); ++i) {
        locations.append(ui->listWidget->item(i)->text());
    }

    // 调用 findAndDisplayLocations 函数
    findAndDisplayLocations(searchText, locations);
}

// 处理坐标点击事件
void MainWindow::onCoordinatesClicked(int x, int y)
{
    qDebug() << "MainWindow 接收到点击坐标: (" << x << "," << y << ")";

    // 将点击坐标转化为景点序号
    int index = ui->travelLabel->findInterestByLocation(x, y);
    if (index == -1) {
        return;
    }

    pointQueue.push_back(index);
    ui->Qcout->clear();

    if (pointQueue.size() <= 1) {
        return;
    }

    QVector<int> route;
    QString algoselect = ui->RouteSolution->currentText();
    if (algoselect == "SPFA") {
        route = SpfaConvert(pointQueue);
    } else if (algoselect == "dijkstra") {
        route = dijkstraConvert(pointQueue);
    } else if (algoselect == "Astar"){
        route = AstarConvert(pointQueue);
    }

    ui->travelLabel->setConnectionSequence(route);
    Navi(route);
}

// TSP 按钮点击事件
void MainWindow::onTSPButtonClicked()
{
    QVector<int> result = TSPSolve(InterestMatrix);

    for (int &resultcity : result) {
        resultcity += 30; // 调整城市编号
    }

    // 确保 51 是结果的第一个元素（形成一个循环）
    int index = result.indexOf(50);
    if (index != -1) {
        std::rotate(result.begin(), result.begin() + index, result.end());
    }
    result.append(50);

    // 设置转换后的序列并显示结果
    QString algoselect = ui->RouteSolution->currentText();
    if (algoselect == "SPFA") {
        ui->travelLabel->setConnectionSequence(dijkstraConvert(result));
    } else if (algoselect == "dijkstra") {
        ui->travelLabel->setConnectionSequence(SpfaConvert(result));
    }else if (algoselect == "Astar"){
        ui->travelLabel->setConnectionSequence(AstarConvert(result));
    }

    Navi(dijkstraConvert(result));
}

// TSP 求解函数
QVector<int> MainWindow::TSPSolve(const QVector<QVector<double>> &InterestMatrix)
{
    QString solution = ui->TSPSolution->currentText();
    QVector<int> result;
    QString text;

    if (solution == "遗传算法") {
        GeneticAlgorithm ga(InterestMatrix, 100, 1000, 0.15);
        Individual bestSolution = ga.solve();
        for (int city : bestSolution.path) {
            result.push_back(city);
        }

        text = "Total distance: " + QString::number(1.0 / bestSolution.fitness, 'f', 2);
    } else if (solution == "蚁群算法") {
        int numAnts = 10;
        int generations = 100;
        double alpha = 1.0;
        double beta = 5.0;
        double evaporationRate = 0.5;
        AntColonyOptimization aco(InterestMatrix, numAnts, generations, alpha, beta, evaporationRate);
        QVector<int> bestSolution = aco.solve();
        for (int city : bestSolution) {
            result.push_back(city);
        }

        text = "Total distance: " + QString::number(aco.calculateDistance(bestSolution), 'f', 2);
    }

    ui->Qcout->clear();
    ui->Qcout->append(text);
    return result;
}

// 使用 SPFA 算法转换路径
QVector<int> MainWindow::SpfaConvert(const QVector<int> &sequence)
{
    QVector<int> output;
    for (int i = 0; i < sequence.size() - 1; i++) {
        SPFAResult spfaresult = spfa(distanceMatrix, sequence[i]);
        QVector<int> path = getPath(spfaresult.predecessors, sequence[i], sequence[i + 1]);
        for (int point : path) {
            if (!std::empty(output) && *output.rbegin() == point) {
                continue;
            }
            output.push_back(point);
        }
    }
    return output;
}

// 使用 Dijkstra 算法转换路径
QVector<int> MainWindow::dijkstraConvert(const QVector<int> &sequence)
{
    QVector<int> output;
    for (int i = 0; i < sequence.size() - 1; i++) {
        QPair<double, QVector<int>> result = dijkstra(distanceMatrix, sequence[i], sequence[i + 1]);
        QVector<int> path = result.second;
        for (int point : path) {
            if (!output.isEmpty() && output.last() == point) {
                continue;
            }
            output.push_back(point);
        }
    }
    return output;
}
QVector<int> MainWindow::AstarConvert(const QVector<int> &sequence){
    QVector<int> output;
    for (int i = 0; i < sequence.size() - 1; i++) {
        QPair<double, QVector<int>> result = AStarAlgorithm::aStar(sequence[i],sequence[i + 1],distanceMatrix,geoVector);
        QVector<int> path = result.second;
        for (int point : path) {
            if (!output.isEmpty() && output.last() == point) {
                continue;
            }
            output.push_back(point);
        }
    }
    return output;
}


// 清除按钮点击事件
void MainWindow::on_ClearButton_clicked()
{
    QVector<int> cl;
    pointQueue = cl;
    ui->travelLabel->setConnectionSequence(pointQueue);
    ui->Qcout->clear();
}

// 导航功能
void MainWindow::Navi(QVector<int> route)
{
    if (route.size() <= 1) {
        return;
    }

    ui->Qcout->clear();

    for (int i = 0; i < route.size() - 1; i++) {
        QString directionSymbol = "⬇\n⬇";
        QString directionText;
        QPointF point1 = positionsMap[names.at(route[i])];
        QPointF point2 = positionsMap[names.at(route[i + 1])];

        if (i > 0) {
            QPointF point0 = positionsMap[names.at(route[i - 1])];
            double angle = std::atan2(point2.y() - point1.y(), point2.x() - point1.x()) -
                           std::atan2(point1.y() - point0.y(), point1.x() - point0.x());
            angle = std::fmod(angle + 3 * M_PI, 2 * M_PI) - M_PI;

            if (std::abs(angle) > 5 * M_PI / 6) {
                directionText = "     调头";
            } else if (std::abs(angle) < M_PI / 6) {
                directionText = "     直行";
            } else if (angle > 0) {
                if (angle > 4 * M_PI / 6) {
                    directionText = "     左转调头";
                } else {
                    directionText = "     左转";
                }
            } else {
                if (angle < -4 * M_PI / 6) {
                    directionText = "     右转调头";
                } else {
                    directionText = "     右转";
                }
            }
        } else {
            directionText = "     直行";
        }

        double distance = floydMatrix[route[i]][route[i + 1]];

        QString locationName = names.at(route[i]);
        if (locationName.contains("导航点")) {
            locationName = "前方路口" + locationName;
        }

        ui->Qcout->append(locationName);
        ui->Qcout->append(directionSymbol + directionText + QString::number(distance) + "米");
        ui->Qcout->append("⬇");
    }

    QString lastLocationName = names.at(route[route.size() - 1]);
    if (lastLocationName.contains("导航点")) {
        lastLocationName = "路口";
    }
    ui->Qcout->append(lastLocationName);
}

// 计算颜色
QColor calculateColor(int currentLength, int minLength, int maxLength)
{
    if (maxLength == minLength) {
        return QColor(0, 255, 0); // 所有景点长度一样时，显示绿色
    }

    float ratio;
    if (currentLength < maxLength) {
        ratio = float(currentLength - minLength) / (maxLength - minLength);
    } else if (minLength > currentLength) {
        ratio = 0;
    } else {
        ratio = 1;
    }

    int red = static_cast<int>(255 * ratio);
    int green = static_cast<int>(255 * (1 - ratio));
    int blue = 0;
    return QColor(red, green, blue);
}

// 根据队列长度计算颜色
void MainWindow::calculateColorByQueueLength(double arrivalRate)
{
    QVector<QString> location;
    for (int i = 30; i < names.length(); i++) {
        location.push_back(names[i]);
    }

    QueueNetwork network(InterestMatrix, location, arrivalRate);
    network.calculateTraffic();
    network.calculateQueueMetrics();
    lengths = network.returnLength();

    QVector<QColor> colors;
    for (double length : lengths) {
        QColor color = calculateColor(length, 0, 15);
        colors.push_back(color);
    }
    ui->travelLabel->setPointColor(colors);
}

// 到达率改变时的槽函数
void MainWindow::on_arrivalRate_valueChanged(int value)
{
    calculateColorByQueueLength(value);
}

// 安排按钮点击事件
void MainWindow::on_Arrange_clicked()
{
    if (lengths.size() < 21) {
        return;
    }

    QVector<int> index;
    for (int i = 0; i < lengths.size(); i++) {
        if (lengths[i] < 10) {
            index.push_back(i + 30);
        }
    }
    if (index.indexOf(50) == -1) {
        index.push_back(50);
    }

    QVector<QVector<double>> InterestMatrixByIndex;

    for (int i = 0; i < index.size(); i++) {
        QVector<double> row;
        for (int j = 0; j < index.size(); j++) {
            row.push_back(floydMatrix[index[i]][index[j]]);
        }
        InterestMatrixByIndex.push_back(row);
    }

    QVector<int> route = TSPSolve(InterestMatrixByIndex);
    QVector<int> result;
    for (int city : route) {
        result.push_back(index[city]);
    }

    int index50 = result.indexOf(50);
    if (index50 != -1) {
        std::rotate(result.begin(), result.begin() + index50, result.end());
    }
    result.append(50);

    QString algoselect = ui->RouteSolution->currentText();
    if (algoselect == "SPFA") {
        ui->travelLabel->setConnectionSequence(dijkstraConvert(result));
    } else if (algoselect == "dijkstra") {
        ui->travelLabel->setConnectionSequence(SpfaConvert(result));
    }

    Navi(dijkstraConvert(result));
}
